package com.qianfeng.openapi.web.master.interceptor;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qianfeng.openapi.common.constant.OpenApiConstants;
import com.qianfeng.openapi.common.enums.OpenApiEnums;
import com.qianfeng.openapi.common.util.JSONUtil;
import com.qianfeng.openapi.web.master.pojo.AdminUser;
import com.qianfeng.openapi.web.master.pojo.Menu;
import com.qianfeng.openapi.web.master.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class AuthenticationInterceptor implements HandlerInterceptor {

    @Value("${ignoreUrls}")
    private String ignoreUrls;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1. 获取当前的请求路径
        String uri = request.getRequestURI();

        //2. 将ignoreUrls用','进行分割,分割后进行遍历
        for (String ignoreUrl : ignoreUrls.split(",")) {
            //2.1 如果请求路径中包含需要放行的路径,直接return true
            if (uri.contains(ignoreUrl)) {
                return true;
            }
        }

        /*//3. 通过request获取session对象
        HttpSession session = request.getSession();

        //4. 通过session获取当前用户登录的信息
        AdminUser adminUser = (AdminUser) session.getAttribute(OpenApiConstants.USER_SESSION);*/

        //3. 获取cookie中存放的key
        String keySuffix = null;
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (OpenApiConstants.KEY.equals(cookie.getName())) {
                    keySuffix = cookie.getValue();
                }
            }
        }
        if (keySuffix == null) {
            //5.1 重定向到登录页面 , return false;
            log.info("【权限校验拦截器】 用户未登录,木有权限!");
            response.sendRedirect(request.getContextPath() + "/login.html");
            return false;
        }

        String value = redisTemplate.opsForValue().get(OpenApiConstants.USER_REDIS + keySuffix);
        //4. 从Redis中获取用户信息,并反序列化为对象
        if (value == null) {
            //5.1 重定向到登录页面 , return false;
            log.info("【权限校验拦截器】 用户超时!!");
            response.sendRedirect(request.getContextPath() + "/login.html");
            return false;
        }
        AdminUser adminUser = JSONUtil.fromJSON(value, AdminUser.class);
        redisTemplate.expire(OpenApiConstants.USER_REDIS + keySuffix, OpenApiConstants.REDIS_TIMEOUT, TimeUnit.SECONDS);
        //5. 如果用户登录信息为null.
        if (adminUser == null) {
            //5.1 重定向到登录页面 , return false;
            log.info("【权限校验拦截器】 用户未登录,木有权限!");
            response.sendRedirect(request.getContextPath() + "/login.html");
            return false;
        }


        //6. 判断当前登录用户是否有操作当前路径的权限
        /*//6.1 从session域中获取到当前用户拥有的权限信息
        List<Menu> menuList = (List<Menu>) session.getAttribute(OpenApiConstants.USER_MENU);*/
        //6.1 从Redis中获取用户权限信息
        ObjectMapper objectMapper = new ObjectMapper();
        String menuJson = redisTemplate.opsForValue().get(OpenApiConstants.USER_MENU_REDIS + keySuffix);
        if (menuJson == null) {
            //5.1 重定向到登录页面 , return false;
            log.info("【权限校验拦截器】 用户权限超时!");
            response.sendRedirect(request.getContextPath() + "/login.html");
            return false;
        }
        List<Menu> menuList = objectMapper.readValue(menuJson, new TypeReference<List<Menu>>() {
        });
        redisTemplate.expire(OpenApiConstants.USER_MENU_REDIS + keySuffix, OpenApiConstants.REDIS_TIMEOUT,TimeUnit.SECONDS);
        //6.2 遍历菜单集合
        for (Menu menu : menuList) {
            String url = menu.getUrl();
            if (!StringUtils.isEmpty(url) && uri.contains(url)) {
                // 拥有权限
                // 直接放行
                return true;
            }
        }
        //6.3 没有权限,重定向到401.html页面
        String requestType = request.getHeader("X-Requested-With");
        if (StringUtils.isEmpty(requestType)) {
            // 传统请求
            response.sendRedirect(request.getContextPath() + "/401.html");
        } else {
            // ajax请求
            response.setContentType("application/json;charset=utf-8");
            ObjectMapper mapper = new ObjectMapper();
            String json = mapper.writeValueAsString(R.error(OpenApiEnums.NOT_AUTHOR));
            response.getWriter().write(json);
        }
        return false;
    }
}
